Skip to content

feat(tron): return live data from listAccountAssets and getAccountBalances - #388

Merged
ulissesferreira merged 4 commits into
mainfrom
WPN-2217-list-account-assets-live-data
Oct 6, 2026
Merged

ulissesferreira merged 4 commits into
mainfrom
WPN-2217-list-account-assets-live-data

Conversation

@ulissesferreira

@ulissesferreira ulissesferreira commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Explanation

listAccountAssets and getAccountBalances in the Tron Snap previously returned whatever was persisted in the Snap's state, so the data was only as fresh as the last cronjob indexation. This is needed so the assets controller can use the Snap as the data source for reconcile when the asset migration feature flag switches back.

Changes:

  • getAccountAssets (listAccountAssets) and getAccountBalances in the keyring now fetch live assets and balances from the chain (via fetchAccountAssetsFromTrongrid) instead of reading persisted state. Fetch failures propagate to the caller.
  • getAccountBalances only fetches live data for the scopes the requested assets belong to, avoiding unnecessary chain calls.
  • Added AssetsService.fetchAccountAssets, a migration-aware live fetch: when the migration is active it goes through the AssetsController fetch pipeline (getAssets with forceUpdate and bypassServerCache, so the Core messenger now includes AssetsControllerGetAssetsAction), otherwise it hits TronGrid directly through the Snap adapter.
  • Added AssetsService.fetchAccountAssetsFromTrongrid, a fallback that always fetches live data from TronGrid regardless of the migration feature flag.
  • CoreAssetsAdapter no longer queries TronGrid directly; its live fetch goes through the AssetsController pipeline. The TronGrid extraction logic (staking, bandwidth, energy, etc.) now only lives in the Snap adapter.
  • AccountsService.synchronizeAssets now fetches assets per account across all the account's scopes (via fetchAccountAssets) instead of per account × activeNetworks scope combination.

Behavior by assets migration feature flag

The flag is SNAPS_ASSETS_MIGRATION_FLAG_KEYS.tron (any migration stage other than Off counts as ON), checked in AssetsService.#shouldReturnAssetsFromCore().

Method Flag ON - migration active Flag OFF
Keyring.getAccountAssets Live fetch - local TronGrid client Live fetch - local TronGrid client
Keyring.getAccountBalances Live fetch - local TronGrid client Live fetch - local TronGrid client
AssetsService.getAccountAssets AssetsController state Snap's state
AssetsService.getAccountAssetsByIDs AssetsController state Snap's state
AssetsService.getAccountAssetByID AssetsController state Snap's state
AssetsService.fetchAccountAssets Live fetch - AssetsController pipeline (getAssets with forceUpdate + bypassServerCache) Live fetch - local TronGrid client
AssetsService.fetchAccountAssetsFromTrongrid Live fetch - local TronGrid client Live fetch - local TronGrid client
AssetsService.saveMany Publishes keyring events Publishes keyring events + Local persistence

Note: when the flag is ON, the keyring methods fetch live data via TronGrid while the controller path fetches via the AssetsController pipeline — two different live-data sources, and the keyring one may include assets the controller would not return (ownership filtering).

References

Ticket: WPN-2217

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch 3 times, most recently from 3670b04 to baff8e5 Compare September 30, 2026 11:13
@ulissesferreira ulissesferreira changed the title feat(WPN-2217): return live data from listAccountAssets and getAccountBalances feat(tron-wallet-snap): return live data from listAccountAssets and getAccountBalances Sep 30, 2026
@ulissesferreira ulissesferreira changed the title feat(tron-wallet-snap): return live data from listAccountAssets and getAccountBalances feat(tron-wallet-snap): return live data from listAccountAssets and getAccountBalances Sep 30, 2026
@ulissesferreira ulissesferreira changed the title feat(tron-wallet-snap): return live data from listAccountAssets and getAccountBalances feat(tron): return live data from listAccountAssets and getAccountBalances Sep 30, 2026
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch 2 times, most recently from ebc77b5 to 8133f76 Compare September 30, 2026 13:12
@ulissesferreira
ulissesferreira marked this pull request as ready for review September 30, 2026 13:25
@ulissesferreira
ulissesferreira requested a review from a team as a code owner September 30, 2026 13:25
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch 4 times, most recently from 822392c to 06f231f Compare September 30, 2026 13:45
async fetchAccountAssets(account: KeyringAccount): Promise<AssetEntity[]> {
const results = await Promise.all(
account.scopes.map((scope) =>
this.fetchAccountAssetsByScope(account, scope as Network),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we relax fetchAccountAssetsByScope's scope argument type to accept ${string}:${string}, or add a type guard here so we don't need this cast?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm very good idea, as is definitely to be avoided. Let me give it a try.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is we are using Network everywhere as the required type. So basically, somehow, we need to convert the input on handlers and then have Network internally which is more specific

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to keep using Network we should add a type guard to narrow down the type from ${string}:${string} so that we throw on unsupported scopes while also making typescript happy - this function seems to be a good place to do it since we take the scope value directly from the KeyringAccount

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100%. I am going to look around the code and see if it makes sense to add some more of that here or open a PR right next to it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be no more than three lines of code before this Promise.all call, so IMO we can do it in this PR, but your call

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the downstream effects of the type change I am going to address in a follow up PR with more type hardening on all things related to Network, scopes, etc.

@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch from 06f231f to 5612e01 Compare September 30, 2026 15:42
@ulissesferreira
ulissesferreira changed the base branch from main to WPN-2217-remove-scope-network-forced-casts September 30, 2026 15:42
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch from 5612e01 to fe369ca Compare September 30, 2026 15:45
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch from fe369ca to 67d43ca Compare September 30, 2026 15:56
@ulissesferreira
ulissesferreira added this pull request to stack #395 September 30, 2026 16:06
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch from 67d43ca to bdbe277 Compare October 1, 2026 15:16
@ulissesferreira
ulissesferreira removed this pull request from stack #395 October 1, 2026 15:17
@ulissesferreira
ulissesferreira changed the base branch from WPN-2217-remove-scope-network-forced-casts to main October 1, 2026 15:17

@stanleyyconsensys stanleyyconsensys left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have a question

when we use listAccountAssets and getAccountBalances from controller
means there will be a case that they dont wanna to use accounts API (becoz accounts API failed)

if im not miss taken, the live data from those 2 methods are returning the result from accounts API

wdyt?

account: KeyringAccount,
scope: Network,
): Promise<AssetEntity[]> {
if (await this.#shouldReturnAssetsFromCore()) {

@stanleyyconsensys stanleyyconsensys Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if i understand correct

shouldReturnAssetsFromCore is reading FF and fetchAccountAssetsByScope is reading data base on this condtion

but there are 2 fallbacks
1 is fallback by FF
2 is fallback becoz accounts API fail and then fallback to snap to get balance, the FF untouch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — this is exactly the coupling we wanted to avoid. Fixed in 1a040f3: fetchAccountAssets (the keyring path) now always hits TronGrid through the Snap adapter regardless of flag state, so the response shape is stable. The flag-gated fan-out stays only in fetchAccountAssetsByScope, which is now exclusive to the asset synchronization flow in AccountsService.

@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch 2 times, most recently from b0c96b3 to 12924fb Compare October 5, 2026 15:20

- Show "Estimated changes are not available" instead of "No estimated changes" when the transaction scan returns an error result, such as for a malformed transaction ([#396](https://github.com/MetaMask/internal-snaps/pull/396))
- Report the MetaMask origin as lowercase `metamask` instead of `MetaMask` for MetaMask-initiated operations, so the origin matches the value used by the other non-EVM snaps and granted to the keyring methods, and so transaction scan requests are attributed to `https://metamask.io`. The confirmation UI keeps displaying `MetaMask`. ([#392](https://github.com/MetaMask/internal-snaps/pull/392))
- Show "Estimated changes are not available" instead of "No estimated changes" when the transaction scan returns an error result, such as for a malformed transaction ([#396](https://github.com/MetaMask/internal-snaps/pull/396))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main has this line duplicated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Match the handler names properly

@ulissesferreira

Copy link
Copy Markdown
Contributor Author

Ready for another look @mikesposito @stanleyyconsensys

@ulissesferreira
ulissesferreira added this pull request to stack #410 October 5, 2026 19:04

@stanleyyconsensys stanleyyconsensys left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a nit comment for improvement


const assetsList = await this.#assetsService.getAccountAssets(accountId);
const assetsList =
await this.#assetsService.fetchAccountAssetsFromTrongrid(account);

@stanleyyconsensys stanleyyconsensys Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

shall we consider adding this.#assetsService.fetchAccountAssetsFromTrongrid with InMemoryCache

as Caller do listAccountAsset first then getAccountBalances

So those SNAP api method use the same tron grid API, we can have a bit optizme to reduce the network call?
e.g

  • listAccountAsset: always return live data + save into in memory cache with expire
  • getAccountBalances: read cache first then read live data if cache not exist

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would start without it. Just to make sure everything works on main. And then optimize it

…ia TronGrid

The keyring methods (listAccountAssets, getAccountBalances) fetched
live data through a feature-flag-gated path: when the assets migration
flag was active the fetch routed through the CoreAssetsAdapter, which
only returns snap-owned assets, changing the response shape based on
flag state.

fetchAccountAssets now always hits TronGrid through the Snap adapter
regardless of the migration stage; the migration-aware fan-out stays
in AssetsService.fetchAccountAssetsByScope for the asset
synchronization flow.
The CoreAssetsAdapter fetched live assets by calling TronGrid directly
(account info, account resources, staking rewards) and rebuilding the
special-asset extraction stack locally, duplicating the fetch pipeline
the AssetsController already owns.

fetchAccountAssets in the CoreAssetsAdapter now goes through the
AssetsController's getAssets action with forceUpdate and
bypassServerCache, so neither client nor server caches are used and the
special assets flow is owned by the controller pipeline. The Snap
adapter keeps the direct TronGrid fetch for the non-migration path, and
fetchAccountAssetsFromTrongrid stays as the flag-independent fallback.
The asset synchronization flow fetches once per account instead of once
per account-and-scope combination.
@ulissesferreira
ulissesferreira force-pushed the WPN-2217-list-account-assets-live-data branch from 12924fb to a1db237 Compare October 6, 2026 08:31
@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@stanleyyconsensys stanleyyconsensys left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ulissesferreira
ulissesferreira added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit ee1d37d Oct 6, 2026
56 checks passed
@ulissesferreira
ulissesferreira deleted the WPN-2217-list-account-assets-live-data branch October 6, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants